<?php
/**
 * Класс RL_Module - абстрактный класс для всех модулей системы
 *
 * @abstract
 * @package mumak
 * @subpackage core
 */
abstract class RL_Module {

	/**
	 * Ссылка на объект RH
	 *
	 * @var RL_SiteRequestHandler
	 */
	public $rh;

	/**
	 * Контекстное окружение
	 *
	 * @var RL_Context_Site
	 */
	public $ctx;

	/**
	 * Универсальный адрес объекта
	 *
	 * @var string
	 */
	public $address;

	/**
	 * Все данные объекта
	 *
	 * @var array
	 */
	protected $data = array();

	/**
	 * Класс объекта модуля
	 *
	 * @var string
	 */
	protected $module_class;

	/**
	 * Набор полей, которые нельзя изменять извне
	 *
	 * Usage:
	 *  Array ( "id" , "_id" , "_parent" )
	 *
	 * @var array
	 */
	protected $private_data_fields = array();

	/**
	 * Конструктор создает объект, но не инициализирует и не загружает его
	 *
	 * @param RL_SiteRequestHandler $rh
	 * @param string $uni_address
	 * @return RL_Module
	 */
	final protected function __construct( RL_SiteRequestHandler $rh , $uni_address )
	{
		$this->rh = $rh;
		$this->ctx = $rh->ctx;
		$this->address = $uni_address;
	}

	/**
	 * Функция для загрузки объекта по ID. Надо перегружать
	 *
	 * @param int $id
	 */
	public function loadById( $module_id ) {}

	/**
	 * Функция для загрузки объекта по юниадресу
	 *
	 * @param string $supertag юниадрес
	 */
	public function loadBySupertag ( $supertag ) {}

	/**
	 * Инициализация объекта после его создания
	 *
	 * @return void
	 */
	public function initialize( &$request_params ) { $this->request = &$request_params; }

	/**
	 * Выполняет метод объекта
	 *
	 * @param string $method название метода
	 * @param array $params параметры, передаваемые в метод
	 * @return RL_Response
	 */
	public function executeMethod( $method , array $params = array())
	{
		$script = $method;

		$result = $this->rh->useClass($this->rh->modules_handlers_dir . $script);

		if(!$result) {
			return $this->ctx->debug->error("ERROR: cannot find handler $method of module " . $this->module_class);
		} 

		$handler = new $method ( $this, $params );
		/* @var $handler RL_Handler */
		$result = $handler->execute();

		return $result;
	}

	/**
	 * Возвращает все данные об объекте
	 *
	 * @return array
	 */
	final public function getData ()
	{
		return $this->data;
	}

	/**
	 * Возвращает значение одного из полей объекта
	 *
	 * @param string $key
	 * @return mixed
	 */
	final public function getDataElement ($key = "")
	{
		if($key == "") {
			return null;
		}

		return $this->data[$key];
	}

	/**
	 * Установить значение одному из полей данных объекта
	 *
	 * @param string $key
	 * @param string $value
	 * @return bool
	 */
	final public function setDataElement ($key, $value)
	{
		if($key == "") {
			return false;
		}

		if(in_array($key , $this->private_data_fields)) {
			return false;
		}

		$this->data[$key] = $value;
	}

	/**
	 * Создает и инициализирует объект, не загружая его, по классу
	 *
	 * @param RL_SiteRequestHandler $rh
	 * @param string $module_class класс объекта
	 * @return RL_Module
	 */
	public static function create ( RL_SiteRequestHandler $rh , $module_class, $uni_address )
	{
		$module = NULL;
	
		$class = "Module_" . ucfirst(strtolower($module_class));

		if ($rh->useClass( $rh->modules_dir . $class )) {
			$module = new $class ( $rh , $uni_address );
		}

		return $module;
	}

	/**
	 * Создает и инициализирует объект, не загружая его, по УРЛу
	 *
	 * @param RL_SiteRequestHandler $rh
	 * @param unknown_type $address
	 * @return unknown
	 */
	public static function createByUrl ( RL_SiteRequestHandler $rh , $address )
	{
		// здесь надо определить класс объекта каким-то образом
		$module_class;

		return self::create( $rh , $module_class );
	}
	
	/**
	 * Определение метода объекта по адресу
	 *
	 * @return string
	 */
	public function getMethod (&$req)
	{
	
		$this->rh->useClass('RL_Utils_Style');
		$action = RL_Utils_Style::camelCase($req['action']);
		$module = RL_Utils_Style::camelCase($this->module_class);

		$method = 'Action_' . $module . "_" . $action;
		return $method;
	} // end of function getMethod
}


